//Recursively list directories with absolute filepaths.
//Without the -d flag, never shows bare directory entries, just files.
//With -d, list only the directories and no files. If no directories are
//specified, use the current working directory as root.
package main

import (
	"flag"
	"os"
	"log"
	"fmt"
	"path/filepath"
)

var Dirs = flag.Bool("d", false, "only show dirs")

func walk(base string, dir *os.File) {
	names, err := dir.Readdirnames(-1)
	if err != nil {
		log.Println(err)
		return
	}

	for _, name := range names {
		name = filepath.Join(base, name)
		file, err := os.Stat(name)
		if err != nil {
			log.Println(err)
			continue
		}

		if file.IsDirectory() {
			if *Dirs {
				fmt.Println(name)
			}
			d, err := os.Open(name)
			if err != nil {
				log.Println(err)
				continue
			}
			walk(name, d)
			d.Close()
		} else if !*Dirs {
			fmt.Println(name)
		}
	}
}

//Usage: %name %flag directories*
func main() {
	log.SetFlags(0)
	flag.Parse()

	base, err := os.Getwd()
	if err != nil {
		log.Fatalln(err)
	}

	dirs := flag.Args()
	if len(dirs) == 0 {
		dirs = []string{base}
	}

	for _, dir := range dirs {
		dir = filepath.Clean(dir)
		if !filepath.IsAbs(dir) {
			dir = filepath.Join(base, dir)
		}

		d, err := os.Open(dir)
		if err != nil {
			log.Fatalln(err)
		}
		s, err := d.Stat()
		if err != nil {
			log.Fatalln(err)
		}
		if !s.IsDirectory() {
			log.Fatalln(dir, "is not a directory")
		}

		walk(dir, d)
		d.Close()
	}
}
